package reflect;

import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;

/**
 *  自动调用当前类Test所在包中所有的类中名字含有s的无参的public方法
 */
public class Test {
    public static void main(String[] args) throws URISyntaxException{
        /*
            1定位Test类所在的目录

            将来在定位一个目录时，使用的相对路径常用的有两个:
            1:当前类所在的目录



            2:当前类所在的根包
            例如:
            一个类的包定义:
            package com.webserver.core;
            public class XXXX{
                ....
            }

            根包位置:
            (com的上一级)com.webserver.core;
                  ^
            以当前类为例：
            package reflect;
            public class Test {...}

            根包位置:
            上一级reflect
              ^
         */

        /*
            定位当前类Test所在的目录
            需要注意，JVM加载的是class文件，所以实际定位的是编译后的Test.class所在的目录
            而不是源码Test.java所在的目录!
         */
        File dir = new File(
            Test.class.getResource(".").toURI()
        );
        //输出该目录的绝对路径
        System.out.println(dir.getAbsolutePath());
        /*
            扫描该目录下的所有class文件，并通过文件名确定类名
         */
        File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
        for(File sub : subs){
            String fileName = sub.getName();//获取该class文件的文件名 例如:Test.class
            String className = fileName.substring(0,fileName.indexOf("."));
            System.out.println("类名:"+className);
            try {
                Class cls = Class.forName("reflect."+className);
                /*
                    Method类提供了获取其表示的方法参数个数的操作:
                    int getParameterCount()
                 */
                Object obj = cls.newInstance();
                //获取当前类的所有本类方法
                Method[] methods = cls.getDeclaredMethods();
                for(Method method : methods){
                    //是否为公开的无参方法
                    if(method.getModifiers()== Modifier.PUBLIC
                            &&
                       method.getParameterCount()==0
                    ){
                        System.out.println("自动执行"+cls.getName()+"的方法:"+method.getName()+"()");
                        method.invoke(obj);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }
}
